package cn.yy.logreportmanager.service.impl;

import cn.yy.logreportmanager.dto.common.Response;
import cn.yy.logreportmanager.dto.common.ResponseBean;
import cn.yy.logreportmanager.dto.report.SaleEntry;
import cn.yy.logreportmanager.dto.report.SaleReportDataBody;
import cn.yy.logreportmanager.entity.Department;
import cn.yy.logreportmanager.entity.Employee;
import cn.yy.logreportmanager.entity.Worklog;
import cn.yy.logreportmanager.mapper.DepartmentMapper;
import cn.yy.logreportmanager.mapper.EmployeeMapper;
import cn.yy.logreportmanager.mapper.WorklogMapper;
import cn.yy.logreportmanager.service.ReportService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    EmployeeMapper employeeMapper;
    @Autowired
    DepartmentMapper departmentMapper;
    @Autowired
    WorklogMapper worklogMapper;

    private static class CondMapKey{
        public final static String deptID = "deptID";
        public final static String cusMgrID = "cusMgrID";
        public final static String timeFrom = "timeFrom";
        public final static String timeTo = "timeTo";
    }
    @Override
    public ResponseBean<?> conditionQuery(Map<String, Object> condMap) {
        // TODO: 浩洋让我改的
        if (condMap.containsKey(CondMapKey.timeFrom)) {
            condMap.put(CondMapKey.timeFrom, parseDateTime(condMap.get(CondMapKey.timeFrom).toString()));
        }
        if (condMap.containsKey(CondMapKey.timeTo)){
            condMap.put(CondMapKey.timeTo, parseDateTime(condMap.get(CondMapKey.timeTo).toString()));
        }

        ResponseBean<?> checkResp = condQueryArgCheck(condMap);
        if (checkResp != null) return checkResp;

        LambdaQueryWrapper<Worklog> queryWrapper = new LambdaQueryWrapper<>();
        if (condMap.containsKey(CondMapKey.deptID)){
            queryWrapper.and(qw -> qw.eq(Worklog::getWDeptId, condMap.get(CondMapKey.deptID)));
        }
        if (condMap.containsKey(CondMapKey.cusMgrID)){
            queryWrapper.and(qw -> qw.eq(Worklog::getWCusMgrId, condMap.get(CondMapKey.cusMgrID)));
        }
        if (condMap.containsKey(CondMapKey.timeFrom)){
            queryWrapper.and(qw -> qw.ge(Worklog::getWTime,condMap.get(CondMapKey.timeFrom)));
        }
        if (condMap.containsKey(CondMapKey.timeTo)){
            queryWrapper.and(qw -> qw.le(Worklog::getWTime,condMap.get(CondMapKey.timeTo)));
        }

        List<Worklog> worklogs = worklogMapper.selectList(queryWrapper);

        return wrapListAsQueryResponse(worklogs);
    }

    private LocalDateTime parseDateTime(String timeStr) {
        DateTimeFormatter fmt = DateTimeFormatter.ISO_INSTANT;
        return LocalDateTime.parse(timeStr, fmt);
    }

    private ResponseBean<?> condQueryArgCheck(Map<String, Object> condMap){
        Set<String> keys = new HashSet<>(condMap.keySet());
        for (String key:keys){
            if (condMap.get(key) == null){
                condMap.remove(key);
            }
        }
        if (condMap.containsKey(CondMapKey.cusMgrID) && condMap.containsKey(CondMapKey.deptID)){
            Employee employee = employeeMapper.selectById((Serializable) condMap.get(CondMapKey.cusMgrID));
            if (employee == null){
                return Response.simpleErr("Employee ID Not Found: " +
                        condMap.get(CondMapKey.cusMgrID),"");
            }
            Department department = departmentMapper.selectById(employee.getEmpDeptId());
            if (department == null) {
                return Response.simpleErr(
                        "Employee ("+ condMap.get(CondMapKey.cusMgrID)+") Not Found " +
                                "in Department ("+ condMap.get(CondMapKey.deptID)+")","");
            }
        }

        if (condMap.containsKey(CondMapKey.timeFrom)
                && !(condMap.get(CondMapKey.timeFrom) instanceof LocalDateTime)){
            return Response.simpleErr("非法的时间格式",condMap.get(CondMapKey.timeFrom).toString());
        }
        if (condMap.containsKey(CondMapKey.timeTo)
                && !(condMap.get(CondMapKey.timeTo) instanceof LocalDateTime)){
            return Response.simpleErr("非法的时间格式", condMap.get(CondMapKey.timeTo).toString());
        }
        return null;
    }

    private ResponseBean<?> wrapListAsQueryResponse(List<Worklog> list){
        List<SaleEntry> entries = list.stream().map(worklog -> {
            SaleEntry entry = new SaleEntry();
            entry.setContent(worklog.getWContent());
            entry.setReportID(worklog.getWId());
            entry.setTime(worklog.getWTime());
            entry.setCusMgrID(worklog.getWCusMgrId());
            entry.setDeptID(worklog.getWDeptId());

            Employee mgr = employeeMapper.selectById(worklog.getWCusMgrId());
            Department dept = departmentMapper.selectById(worklog.getWDeptId());
            entry.setDeptName(dept.getDeptName());
            entry.setCusMgrName(mgr.getEmpName());

            return entry;
        }).collect(Collectors.toList());

        SaleReportDataBody body = new SaleReportDataBody();
        body.setEntries(entries);
        ResponseBean<SaleReportDataBody> responseBean = new ResponseBean<>();
        responseBean.setStatus(Response.STATE_OK);
        responseBean.setBody(body);
        return responseBean;
    }

    @Override
    public ResponseBean<?> newReport(Worklog worklog) {
        Employee employee = employeeMapper.selectById(worklog.getWCusMgrId());

        if (employee == null){
            return Response.simpleErr("Employee ID Not Found: " +
                    worklog.getWCusMgrId(),"");
        }
        // TODO: 浩洋让我改的, deptID 可以随便输
        worklog.setWDeptId(employee.getEmpDeptId());

        Department department = departmentMapper.selectById(employee.getEmpDeptId());
        if (department == null) {
            return Response.simpleErr(
                    "Employee (" + worklog.getWCusMgrId()+") Not Found " +
                            "in Department (" + worklog.getWDeptId() + ")","dept id 不正确");
        }
        worklogMapper.insert(worklog);
        return Response.defaultOk;
    }

    @Override
    public ResponseBean<?> updateReport(Worklog worklog) {
        Employee employee = employeeMapper.selectById(worklog.getWCusMgrId());
        if (employee == null){
            return Response.simpleErr("Employee ID Not Found: " +
                    worklog.getWCusMgrId(),"");
        }
        //TODO: 也是浩洋让我改的
        worklog.setWDeptId(employee.getEmpDeptId());

        Department department = departmentMapper.selectById(employee.getEmpDeptId());
        if (department == null) {
            return Response.simpleErr(
                    "Employee (" + worklog.getWCusMgrId()+") Not Found " +
                            "in Department (" + worklog.getWDeptId() + ")","dept id 不正确");
        }
        if (worklog.getWId() == null || worklogMapper.selectById(worklog.getWId()) == null){
            return Response.simpleErr("cannot update work log:"+worklog.getWId(),
                    "primary key not found.");
        }
        worklogMapper.updateById(worklog);
        return Response.defaultOk;
    }
}
